package com.bving.crawler.config;

import com.bving.crawler.pojo.model.CarTestModel;
import com.bving.crawler.service.ApiService;
import com.bving.crawler.service.ICarTestService;
import com.bving.crawler.util.TitleFilter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @description
 *
 */
//当前任务没有结束不开启下一个任务
@DisallowConcurrentExecution
public class CrawlerAutohomeJobBean extends QuartzJobBean {

    @Autowired
    private ApiService apiService;
    @Autowired
    private ICarTestService carTestService;
    @Autowired
    private TitleFilter titleFilter;

    public static final String URL="https://www.autohome.com.cn/bestauto/";

    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        //获取spring容器
        ApplicationContext applicationContext =(ApplicationContext) context.getJobDetail().getJobDataMap().get("context");

        this.apiService = applicationContext.getBean(ApiService.class);
        this.carTestService= applicationContext.getBean(ICarTestService.class);
        this.titleFilter= applicationContext.getBean(TitleFilter.class);
		
        //循环165页并爬取其中数据
        for (int i = 1; i <= 165; i++) {
            try {
                crawler(URL+i);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
    
	/**
     * 解析并保存数据
     * @param url
     * @throws IOException
     */
    private void crawler(String url) throws IOException {

        //1.爬取数据html
        String html=apiService.getHtml(url);
        //2.使用jsoup解析页面
        Document dom = Jsoup.parse(html);

        //3.获取所有评测的div
        Elements divs = dom.select("#bestautocontent div.uibox");

        //4.遍历当前页所有评测数据
        for (Element div : divs) {
            //去重过滤,重复的数据就不需要再处理了
            String title = div.select("div.uibox-title").first().text();
            if (titleFilter.contains(title)){
                //如果数据存在,表示重复,进行下次遍历
                continue;
            }
            //解析页面，获取评测数据对象
            CarTestModel carTestModel = getCarTestModel(div);

            //解析页面,下载车辆评测图片
            String carImage = getCarImage(div);
            //把汽车数据存到数据库
            carTestModel.setImage(carImage);
            carTestService.save(carTestModel);
        }
    }

    /**
     * 解析传递进来的元素，封装为汽车评测对象
     * @param div
     * @return
     */
    private CarTestModel getCarTestModel(Element div){
        CarTestModel carTestModel = new CarTestModel(null,
                div.select("div.uibox-title").first().text(),
                changeStr2Num(div.select(".tabbox1 dd:nth-child(2) div.dd-div2").first().text()),
                changeStr2Num(div.select(".tabbox1 dd:nth-child(3) div.dd-div2").first().text()),
                changeStr2Num(div.select(".tabbox1 dd:nth-child(4) div.dd-div2").first().text()),
                div.select(".tabbox2 dd:nth-child(2) > div.dd-div1").first().text(),
                div.select(".tabbox2 dd:nth-child(2) > div.dd-div3").first().text(),
                div.select(".tabbox2 dd:nth-child(3) > div.dd-div1").first().text(),
                div.select(".tabbox2 dd:nth-child(3) > div.dd-div3").first().text(),
                div.select(".tabbox2 dd:nth-child(4) > div.dd-div1").first().text(),
                div.select(".tabbox2 dd:nth-child(4) > div.dd-div3").first().text(),
                null,
                new Date(),
                new Date());

        return carTestModel;
    }

    /**
     * 解析传递进来的元素，下载评测图片
     * @param div
     * @return 下载后的图片名字
     */
    private String getCarImage(Element div){
        //声明存放图片的集合
        List<String> images = new ArrayList<>();
        //获取图的url地址
        Elements page = div.select("ul.piclist02 li");
        //遍历评测图片的元素
        for (Element element : page) {
            //获取评测图片的展示地址
            String imagePage = "https:" + element.select("a").attr("href");
            //获取图片展示页面
            String html = apiService.getHtml(imagePage);
            //解析图片展示页面
            Document dom = Jsoup.parse(html);
            //获取图片地址
            String imageUrl ="https:" + dom.getElementById("img").attr("src");
            //下载图片并返回图片名称
            //String imageName = apiService.getImage(imageUrl);
            images.add(imageUrl);
        }

        return ArrayUtils.toString(images);
    }

    /**
     * 把字符串最后一个字符去掉,转为数字,再乘以1000
     * @param str
     */
    private long changeStr2Num(String str){
        String substring = StringUtils.substring(str, 0, str.length() - 1);
        substring = isNumeric(substring.trim())?substring.trim():"0";
        //把字符串转为小数,必须用Number接收,否则会有精度丢失的问题
        Number num = substring.isEmpty() ? 0 : Double.parseDouble(substring.trim())*1000;
        return num.longValue();
    }

    /**
     * 判断字符串是否为数字
     * @param str
     * @return
     */
    public boolean isNumeric(String str) {
        //看它是否能转化为一个数
        try {
            double db=Double.parseDouble(str);
        } catch (Exception e) {
            return false;
        }
        return true;
    }
}